package com.kancy.springcloudconfig;

import com.kancy.springcloudconfig.action.AlgorithmAction;
import com.kancy.springcloudconfig.constants.Constants;
import com.kancy.springcloudconfig.enums.AlgorithmType;
import com.kancy.springcloudconfig.factory.AlgorithmActionFactory;
import com.kancy.springcloudconfig.factory.BeanFactory;
import com.kancy.springcloudconfig.factory.MainFrameBeanNameResolver;
import com.kancy.springcloudconfig.util.CommonUtil;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;

public class MainFrame{

    private MainFrameBeanNameResolver resolver = new MainFrameBeanNameResolver();

    private JComboBox algorithmTypComboBox = BeanFactory.create(beanName("algorithmTypComboBox"), JComboBox.class);
    private JTextArea plainTextArea = BeanFactory.create(beanName("plainTextArea"), JTextArea.class);
    private JTextArea cipherTextArea = BeanFactory.create(beanName("cipherTextArea"), JTextArea.class);
    private JRadioButton jRadioButtonEncrypt = BeanFactory.create(beanName("jRadioButtonEncrypt"), JRadioButton.class);
    private JRadioButton jRadioButtonDecrypt = BeanFactory.create(beanName("jRadioButtonDecrypt"), JRadioButton.class);
    private JPasswordField passwordField = BeanFactory.create(beanName("passwordField"), JPasswordField.class);
    private JPasswordField passwordFieldSalt = BeanFactory.create(beanName("passwordFieldSalt"), JPasswordField.class);
    private JLabel label1 = BeanFactory.create(beanName("label1"), JLabel.class);
    private JLabel label2 = BeanFactory.create(beanName("label2"), JLabel.class);

    /**
     * 默认的行为监听
     */
    private static ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            doPopupMenuActionPerformed(e);
        }
    };

    private void init() {

        JLabel titleLabel = new JLabel("<html>作者:<font color=red>kancy</font></html>");
        JLabel dateLabel = new JLabel("<html>日期:<font color=red>2020年05月15日</font></html>");
        JLabel lineLabel = new JLabel("<html><p>&nbsp;</p></html>");

        titleLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2){
                    showSubMenu(e);
                }
            }
        });

        // 添加控件
        ArrayList list = new ArrayList();
        list.add(titleLabel);
        list.add(dateLabel);
        list.add(lineLabel);
        list.add(new JLabel("算法类型:"));list.add(initAlgorithmTypeComponent());
        list.add(new JLabel("加解类型:"));list.add(initTypeComponent());
        list.add(initLabel1());list.add(initPasswordComponent());
        list.add(initLabel2());list.add(initSaltComponent());
        list.add(new JLabel("明文:"));list.add(initPlainTextAreaComponent());
        list.add(new JLabel("密文:"));list.add(initCipherTextAreaComponent());
        list.add(initExecuteButton());
        addPopupMenu(list);

        // 设置JOptionPane Frame属性
        Frame frame = JOptionPane.getRootFrame();
        frame.setAlwaysOnTop(true);
        JOptionPane.showOptionDialog(null, list.toArray(), Constants.DEFAULT_TITLE,
                JOptionPane.DEFAULT_OPTION,JOptionPane.PLAIN_MESSAGE, null, new Object[]{}, null);
    }

    /**
     * 添加弹框菜单内容
     * @param list
     */
    private void addPopupMenu(ArrayList list) {
        JPopupMenu popupMenu = new JPopupMenu();
        addPopupMenu(popupMenu, Settings.isBatchMode() ? "关闭批量模式" : "开启批量模式", "batchMode");

        // 为每一个组件添加弹出菜单
        for (Object component : list) {
            if (component instanceof JComponent){
                addPopup((Component) component, popupMenu);
            }
        }
        addPopup(plainTextArea, popupMenu);
        addPopup(cipherTextArea, popupMenu);
    }

    /**
     * 弹出菜单事件处理
     * @param e
     */
    private static void doPopupMenuActionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();

        if ("batchMode".equals(actionCommand)){
            Settings.setBatchMode(!Settings.isBatchMode());
            if (e.getSource() instanceof JMenuItem){
                JMenuItem menuItem = (JMenuItem) e.getSource();
                menuItem.setText(Settings.isBatchMode() ? "关闭批量模式" : "开启批量模式");
            }
            return;
        }
    }

    /**
     * 添加弹出菜单项
     * @param popupMenu
     * @param menuName
     * @param actionCommand
     */
    private static void addPopupMenu(JPopupMenu popupMenu, String menuName,String actionCommand) {
        JMenuItem aboutMenuItem = new JMenuItem(menuName);
        aboutMenuItem.setActionCommand(actionCommand);
        aboutMenuItem.addActionListener(actionListener);
        popupMenu.add(aboutMenuItem);
    }

    /**
     * 添加弹出菜单
     * @param component
     * @param popup
     */
    private static void addPopup(Component component, final JPopupMenu popup) {
        component.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }
            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    showMenu(e);
                }
            }
            private void showMenu(MouseEvent e) {
                popup.show(e.getComponent(), e.getX(), e.getY());
            }
        });
    }

    /**
     * 显示子模块 - 新大陆
     */
    private void showSubMenu(MouseEvent e) {
        JLabel titleLabel = new JLabel("<html><font color=red>恭喜您，发现了新大陆！</font></html>");
        JLabel lineLabel = new JLabel("<html><p>&nbsp;</p></html>");
        JButton followMeButton = new JButton("Follow Me"){{
           addActionListener(new ActionListener() {
               @Override
               public void actionPerformed(ActionEvent e) {
                   // 打开浏览器，去项目地址
                   CommonUtil.openURL(Constants.FOLLOW_ME_URL);
               }
           });
        }};


        JButton debugButton = new JButton("查看密码"){{
            addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    StringBuffer sb = new StringBuffer();
                    sb.append("<html>");
                    sb.append("<p>").append("算法:").append(algorithmTypComboBox.getSelectedItem()).append("</p>");
                    if (label1.isVisible()) {
                        sb.append("<p>").append(label1.getText()).append(passwordField.getText()).append("</p>");
                    }
                    if (label2.isVisible()) {
                        sb.append("<p>").append(label2.getText()).append(passwordFieldSalt.getText()).append("</p>");
                    }
                    sb.append("</html>");
                    JOptionPane.showMessageDialog((Component) e.getSource(), sb.toString());
                }
            });
        }};

        ArrayList list = new ArrayList();
        list.add(titleLabel);
        list.add(lineLabel);
        list.add(debugButton);
        list.add(followMeButton);

        JOptionPane.showOptionDialog(e.getComponent().getParent(), list.toArray(), Constants.DEFAULT_MENU_TITLE,
                JOptionPane.DEFAULT_OPTION,JOptionPane.PLAIN_MESSAGE, null, new Object[]{}, null);
    }


    private Object initExecuteButton() {
        JButton executeButton = new JButton();
        executeButton.setText("执行");
        executeButton.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Object selectedItem = algorithmTypComboBox.getSelectedItem();
                AlgorithmAction action = AlgorithmActionFactory.getAction(selectedItem);
                if (action == null){
                    JOptionPane.showMessageDialog(null,"不支持的加解密类型!");
                    return;
                }
                action.execute(e);
            }
        });
        return executeButton;
    }

    private JComboBox initAlgorithmTypeComponent() {
        AlgorithmType[] algorithmTypes = AlgorithmType.values();
        for (AlgorithmType algorithmType : algorithmTypes) {
            if (!Constants.supportAlgorithm.isEmpty()){
                if (Constants.supportAlgorithm.contains(algorithmType)){
                    algorithmTypComboBox.addItem(algorithmType);
                }
            }else{
                algorithmTypComboBox.addItem(algorithmType);
            }
        }
        algorithmTypComboBox.setEnabled(true);
        algorithmTypComboBox.setEditable(false);

        // 默认选择第一个
        algorithmTypComboBox.setSelectedIndex(0);
        AlgorithmAction action = AlgorithmActionFactory.getAction(algorithmTypComboBox.getSelectedItem());
        if (action!=null){
            action.refresh();
        }

        // 添加选项卡选中状态改变的监听器
        algorithmTypComboBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Object item = algorithmTypComboBox.getSelectedItem();
                AlgorithmAction action = AlgorithmActionFactory.getAction(item);
                if (action != null){
                    action.refresh();
                }
            }
        });
        return algorithmTypComboBox;
    }


    private Object initLabel2() {
        return label2;
    }

    private Object initLabel1() {
        return label1;
    }

    private Object initTypeComponent() {
        jRadioButtonEncrypt.setText("加密");
        jRadioButtonDecrypt.setText("解密");
        ButtonGroup operationTypeButtonGroup = new ButtonGroup();
        operationTypeButtonGroup.add(jRadioButtonEncrypt);
        operationTypeButtonGroup.add(jRadioButtonDecrypt);
        jRadioButtonEncrypt.setSelected(true);

        JPanel jPanel = new JPanel();
        jPanel.add(jRadioButtonEncrypt);
        jPanel.add(jRadioButtonDecrypt);
        jPanel.setBorder(new TitledBorder(""));
        jPanel.setLayout(new GridLayout(0,6));
        return jPanel;
    }


    private Object initSaltComponent() {
        return passwordFieldSalt;
    }

    private Object initPasswordComponent() {
        return passwordField;
    }

    private Object initPlainTextAreaComponent() {
        plainTextArea.setRows(1);
        plainTextArea.setColumns(40);
        plainTextArea.setLineWrap(true);
        plainTextArea.setForeground(new Color(109,179,63));

        JScrollPane jScrollPane = new JScrollPane(plainTextArea);
        jScrollPane.setPreferredSize(new Dimension(450, 90));
        return jScrollPane;
    }
    private Object initCipherTextAreaComponent() {
        cipherTextArea.setRows(1);
        cipherTextArea.setColumns(40);
        cipherTextArea.setLineWrap(true);
        cipherTextArea.setForeground(Color.BLUE);

        JScrollPane jScrollPane = new JScrollPane(cipherTextArea);
        jScrollPane.setPreferredSize(new Dimension(450, 90));
        return jScrollPane;
    }

    private String beanName(String name) {
        return resolver.beanName(name);
    }

    public static void startup(){
        setLookAndFeel();
        MainFrame application = new MainFrame();
        application.init();
    }

    private static void setLookAndFeel() {
        try {
            String lookAndFeel = "javax.swing.plaf.nimbus.NimbusLookAndFeel";
            if ("random".equals(Constants.LOOK_AND_FEEL)){
                int random = ThreadLocalRandom.current().nextInt(0, 10000);
                if (random <= 4000){
                    lookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
                }else if(random > 8000){
                    lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";
                }
            }else{
                lookAndFeel = Constants.LOOK_AND_FEEL;
            }
            UIManager.setLookAndFeel(lookAndFeel);
        } catch (Exception e) {
            System.out.println("lookAndFeel set fail.");
        }
    }

}
